# -*- coding: utf-8 -*-
"""
Created on 2018-5-16 11:44:10

@author: river
//https://blog.csdn.net/panda1234lee/article/details/52311593
//https://www.cnblogs.com/faramita2016/p/7784699.html
//https://blog.csdn.net/ice_martin/article/details/61616987#matplotlib绘图和可视化

@https://www.cnblogs.com/hhh5460/p/5189843.html
@https://www.cnblogs.com/hhh5460/p/4322652.html

"""

import os,sys,xlrd,re
import numpy as np
import math
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as pltCanvas
from matplotlib.backends.backend_qt5 import NavigationToolbar2QT as pltToolbar
import matplotlib.pyplot as plt

import PyQt5 as QT
from PyQt5 import QtCore, QtWidgets, QtGui
import random

FloatRe = re.compile(r'^[-+]?[0-9]+\.[0-9]+$')       # 定义浮点数正则表达式

class MainWindow(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.ui_init()

        self.fire = []
        self.human =  []
        self.reject = []
        self.filename = ""
        self.readflag = False
        self.channel = 0
        self.filetype = 0
        self._vref = 0.99

        self.fzero = 16750
        self.hzero = 17100
        self.rzero = 16100

    def ui_init(self):
        self.resize(1200,600)
        self.setWindowTitle("FireTools")
        self.setAutoFillBackground(True)

        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(1,1,1)
        #self.ax.hold(False)
        #self.ax1 = self.fig.add_subplot(2,1,2)
        #self.ax1.hold(False)

        #main layout
        layout = QtWidgets.QVBoxLayout()

        # file layout
        #qw0 = QtWidgets.QWidget(self)
        flayout = QtWidgets.QHBoxLayout()
        #qw0.setLayout(flayout)

        self.FileTxtEdit = QtWidgets.QTextEdit()
        self.FileTxtEdit.setFixedHeight(25)

        flayout.addWidget(self.FileTxtEdit)

        layout.addLayout(flayout)

        # radio layout
        #qw_radio = QtWidgets.QWidget(self)
        radio_layout = QtWidgets.QHBoxLayout()
        #qw_radio.setLayout(radio_layout)

        self.radioGroup1 = QtWidgets.QButtonGroup(radio_layout)
        txtRadio = QtWidgets.QRadioButton("Txt文件", self)
        txtRadio.setFocusPolicy(QtCore.Qt.NoFocus)
        self.radioGroup1.addButton(txtRadio, 0)
        txtRadio.setChecked(True)
        txtRadio.toggled.connect(self._fileSel)

        excelRadio = QtWidgets.QRadioButton("Excel文件", self)
        excelRadio.setFocusPolicy(QtCore.Qt.NoFocus)
        self.radioGroup1.addButton(excelRadio, 1)
        excelRadio.setChecked(False)
        excelRadio.toggled.connect(self._fileSel)

        self.radioGroup2 = QtWidgets.QButtonGroup(radio_layout)
        sel3Radio = QtWidgets.QRadioButton("三通道", self)
        sel3Radio.setFocusPolicy(QtCore.Qt.NoFocus)
        self.radioGroup2.addButton(sel3Radio, 0)
        sel3Radio.setChecked(True)
        sel3Radio.toggled.connect(self._selCh)

        sel1Radio = QtWidgets.QRadioButton("单通道", self)
        sel1Radio.setFocusPolicy(QtCore.Qt.NoFocus)
        self.radioGroup2.addButton(sel1Radio, 1)
        sel1Radio.setChecked(False)
        sel1Radio.toggled.connect(self._selCh)

        radio_layout.addWidget(txtRadio)
        radio_layout.addWidget(excelRadio)
        radio_layout.addWidget(sel3Radio)
        radio_layout.addWidget(sel1Radio)

        layout.addLayout(radio_layout)

        # function button layout
        #qw1 = QtWidgets.QWidget(self)
        blayout = QtWidgets.QHBoxLayout()
        #qw1.setLayout(blayout)

        openbutton = QtWidgets.QPushButton('打开')
        openbutton.clicked.connect(self.open)
        drawbutton = QtWidgets.QPushButton('原始波形')
        drawbutton.clicked.connect(self.draw)
        filterbutton = QtWidgets.QPushButton('滑动滤波')
        filterbutton.clicked.connect(self.filter)
        algbutton = QtWidgets.QPushButton('算法处理')
        algbutton.clicked.connect(self.algorithm)

        blayout.addWidget(openbutton)
        blayout.addWidget(drawbutton)
        blayout.addWidget(filterbutton)
        blayout.addWidget(algbutton)

        #blayout.addStretch(0)
        layout.addLayout(blayout)

        #plt layout
        #qw2 = QtWidgets.QWidget(self)
        pltlayout = QtWidgets.QVBoxLayout()
        #qw2.setLayout(pltlayout)

        self.canvas = pltCanvas(self.fig)
        self.toolbar = pltToolbar(self.canvas, self)

        pltlayout.addWidget(self.toolbar)
        pltlayout.addWidget(self.canvas)

        layout.addLayout(pltlayout)
        layout.setSpacing(10)
        self.setLayout(layout)

    def _selCh(self):
        if self.radioGroup2.checkedId() == 0:
            self.channel = 0
        else:
            self.channel = 1
        #print("channel={0}".format(self.channel))

    def _fileSel(self):
        if self.radioGroup1.checkedId() == 0:
            self.filetype = 0
        else:
            self.filetype = 1
        #print("filetype={0}".format(self.filetype))

    def open(self):
        if self.filetype == 1:
            fl, _ = QtWidgets.QFileDialog.getOpenFileName(self, "选择文件", "", "Excel File(*.xls)") # "Excel File(*.xls);;All File(*)"
        else:
            fl, _ = QtWidgets.QFileDialog.getOpenFileName(self, "选择文件", "", "Txt File(*.txt)")
        if fl:
            self.filename = fl
            self.FileTxtEdit.setText(self.filename)
            self.read()

    def read(self):
        if self.filetype == 1:
            self._readExcel()
        else:
            self._readTxt()

    def _readTxt(self):
        self.fire = []
        self.human = []
        self.reject = []
        try:
            with open(self.filename) as f:
                for i, s in enumerate(f):
                    if i == 0:
                        v = s.rsplit(",")
                        if v[0].isdigit() and v[1].isdigit() and v[2].isdigit() and (len(v) == 4 and ("zero" in v[3])):
                            self.fzero = int(v[0])
                            self.hzero = int(v[1])
                            self.rzero = int(v[2])
                            print("fzero={0}, hzero={1}, rzero={2}".format(self.fzero, self.hzero, self.rzero))
                            continue
                    s = s[:17]
                    v = s.rsplit(",")
                    if len(v) == 3:
                        if v[0].isdigit() and v[1].isdigit() and v[2].isdigit():
                            if self.channel == 0:
                                self.fire.append(int(v[0]))
                                self.human.append(int(v[1]))
                                self.reject.append(int(v[2]))
                                self.readflag = True
                            else:
                                self.fire.append(int(v[0]))
                                self.readflag = True
        except Exception as e:
            QtWidgets.QMessageBox.warning(self, "warning", str(e)[:64])

    def _readExcel(self):
        try:
            wb = xlrd.open_workbook(self.filename)
            self.fire = []
            self.human = []
            self.reject = []
            self.fzero = 16750
            self.hzero = 17100
            self.rzero = 16100
            for s in wb.sheets():
                for row in range(s.nrows):
                    val = []
                    for col in range(s.ncols):
                        val.append(s.cell(row, col).value)
                    if self.channel == 0:
                        if isinstance(val[0], float) and isinstance(val[1], float) and isinstance(val[2], float):
                            self.fire.append(val[0])
                            self.human.append(val[1])
                            self.reject.append(val[2])
                            self.readflag = True
                    else:
                        if isinstance(val[0], float):
                            self.fire.append(val[0])
                        self.readflag = True
        except Exception as e:
            QtWidgets.QMessageBox.warning(self, "warning", str(e)[:64])

    def _filter(self, data, filter=5):
        ff = []
        if len(data) < filter:  return ff

        ssum = sum(data[:filter])
        ff.append(ssum / filter)
        for i in range(len(data) - filter):
            ssum -= data[i]
            ssum += data[i + filter]
            ff.append(ssum / filter)
        return ff

    def draw(self):
        if self.readflag:
            try:
                self.ax.cla()
                if self.channel == 0:
                    self.ax.plot(range(len(self.fire)), self.fire, 'r', range(len(self.human)), self.human, 'g', range(len(self.reject)), self.reject, 'c')
                    self.ax.legend(['fire', 'man', 'rej'])
                else:
                    self.ax.plot(range(len(self.fire)), self.fire, 'r')
                    self.ax.legend(['fire'])
                self.ax.grid(True)
                self.canvas.draw()
            except Exception as e:
                QtWidgets.QMessageBox.warning(self, "warning", str(e)[:64])

    def filter(self):
        if self.readflag:
            try:
                self.ax.cla()
                f = self._filter(self.fire, 40)
                if self.channel == 0:
                    h = self._filter(self.human, 40)
                    r = self._filter(self.reject, 40)
                    self.ax.plot(range(len(f)), f, 'r', range(len(h)), h, 'g', range(len(r)), r, 'c')
                    self.ax.legend(['fire', 'man', 'rej'])
                else:
                    self.ax.plot(range(len(f)), f, 'r')
                    self.ax.legend(['fire'])
                self.ax.grid(True)
                self.canvas.draw()
            except Exception as e:
                QtWidgets.QMessageBox.warning(self, "warning", str(e)[:64])

    def algorithm(self):
        if not self.readflag: return
        if self.channel == 1: return
        vf = []
        for i, v in enumerate(self.fire):
            tmp = (math.fabs(v-self.fzero))*3.3/32767.0
            tmp *= tmp
            if i > 0:tmp += (vf[i - 1]*self._vref)
            vf.append(tmp)
        vh = []
        for i, v in enumerate(self.human):
            tmp = math.fabs(v - self.hzero) * 3.3/32767.0
            tmp *= tmp
            if i > 0: tmp += (vh[i - 1]*self._vref)
            vh.append(tmp)
        vr = []
        for i, v in enumerate(self.reject):
            tmp = math.fabs(v - self.rzero) * 3.3/32767.0
            tmp *= tmp
            if i > 0: tmp += (vr[i - 1]*self._vref)
            vr.append(tmp)
        vxf, vxd1, vxd2 = 0.0, 0.0, 0.0
        ro0 = []
        ro1 = []
        aaa = []
        aa = 0
        taa = 10
        kkk = min(len(vf), len(vh), len(vr))
        mF, mH, mR = 0.0, 0.0, 0.0
        mFCnt, mHCnt, mRCnt = 0, 0, 0
        mPeak = 0
        mPeakCnt = 0
        mPeakMaxCnt = 0
        try:
            threshold = 0.0
            vfCnt = 0
            taa = 10
            bak = 0
            flag = 0
            FIRET = 0.8
            for i in range(kkk):
                tmp = (1.8*vf[i] - vh[i] - vr[i])/1.6
                vxf = self._vref*vxf + tmp*tmp
                tmp = (-0.2*vf[i] + 9.0*vh[i] - 7.0*vr[i]) / 3.2
                vxd1 = self._vref * vxd1 + tmp * tmp
                tmp = (-0.2*vf[i] - 7.0*vh[i] + 9.0*vr[i]) / 3.2
                vxd2 = self._vref * vxd2 + tmp * tmp

                if (mPeak == 1) and (vf[i] > 6.4) and (vh[i] < FIRET) and (vr[i] < FIRET):
                    if mPeakCnt == 0: print("mPeakCnt start {0}".format(i))
                    mPeakCnt += 1
                    if mPeakCnt >= mPeakMaxCnt:  #峰值超时
                        mPeakCnt = 0
                        mPeak = 0
                        print("mpeak overtime {0}".format(i))

                if (mPeak == 0):
                    if (vf[i] < FIRET or vh[i] < FIRET or vr[i] < FIRET):
                        mF, mH, mR = 0.0, 0.0, 0.0
                        mFCnt, mHCnt, mRCnt = 0, 0, 0
                        mPeakCnt = 0
                    else:
                        if mF < vf[i]:
                            mF = vf[i]
                            mFCnt = 0
                        elif mF > vf[i] + 2.0:
                            mFCnt = 1
                        if mH < vh[i]:
                            mH = vh[i]
                            mHCnt = 0
                        elif mH > vh[i] + 2.0:
                            mHCnt = 1
                        if mR < vr[i]:
                            mR = vr[i]
                            mRCnt = 0
                        elif mR > vr[i] + 2.0:
                            mRCnt = 1
                        if mF > 10.0 and mH > 10.0 and mR > 10.0 \
                            and (mFCnt == 1) and (mHCnt == 1) and (mRCnt == 1) \
                            and (mF < 8.0 * mR) and (mF < 8.0 * mH):
                            mPeak = 1
                            mPeakCnt = 0
                            mPeakMaxCnt = 4 * 125
                            if mF > 50.0 or mH > 50.0 or mR > 50.0: mPeakMaxCnt = 10 * 125
                            print("mpeak=1, {0}, mF{1:.1f}-{2:.1f}, mH{3:.1f}-{4:.1f}, mR{5:.1f}-{6:.1f}".format(i, mF, vf[i], mH, vh[i], mR, vr[i]))

                if (mPeak == 1) and vf[i] < 8.0*FIRET and vh[i] < FIRET and vr[i] < FIRET:
                    mF, mH, mR = 0.0, 0.0, 0.0
                    mFCnt, mHCnt, mRCnt = 0, 0, 0
                    mPeak = 0
                    print("mpeak=0, mpeakcnt={1}, {0}".format(i, mPeakCnt))
                    mPeakCnt = 0

                kVref = 8.0
                kVreflag = 1
                if (vh[i] < FIRET) and (vr[i] < FIRET):
                    if vfCnt <= 1250:
                        vfCnt += 1
                    else:
                        kVreflag = 0
                else:
                    vfCnt = 0
                    kVerflag = 1

                if kVreflag == 1 or 1:
                    M = vf[i] / vxd1
                    N = vxd2 / vxd1
                    P = vf[i] / vxd2
                    t1 = ((0.1 * M + 0.8 * N + 1.0) / math.sqrt((M + 1.0 + N) * (0.01 * M + 0.64 * N + 1.0)))
                    ro0.append(100.0 * t1)
                    t2 = ((0.1 * P + 0.8 / N + 1.0) / math.sqrt((P + 1.0 + 1.0 / N) * (0.01 * P + 0.64 / N + 1.0)))
                    ro1.append(100.0 * t2)
                else:
                    ro0.append(50.0)
                    ro1.append(50.0)

                if (vf[i] > FIRET) and (mPeak == 0) and (vf[i] > kVref*vh[i]) and (vf[i] > kVref*vr[i]) and (kVreflag == 0 or ((t1 > 0.919999) and (t2 > 0.919999))) :
                    if aa <= 400: aa += 1
                    if vf[i] > threshold: threshold = vf[i]
                    bak = aa
                    if aa == 375 and flag == 0:
                        taa = 12
                        flag = 1
                        print("alarm on {0:.2f}E,K{1},{2}s".format(vf[i], kVreflag, i))
                else:
                    if (aa > 0) and (vf[i] < FIRET or (vf[i] < vh[i]*kVref*0.5 or vf[i] < vr[i]*kVref*0.5)):
                        aa -= 1
                        #if vf[i] < max(0.1, threshold*0.005): aa = 0;
                    if aa <= 10 and flag == 1:
                        taa = 10
                        aa = 0
                        flag = 0
                        print("alarm off {0:.2f}E,{1}P,{2}s".format(threshold, bak, i))
                        threshold = 0.0
                aaa.append(taa)
        except Exception as e:
            print(str(e))
            pass
        print('{0}:{1}:{2}'.format(len(vf), len(vh), len(vr)))
        self.ax.cla()
        self.ax.plot(range(len(vf)), vf, 'r', range(len(vh)), vh, 'g', range(len(vr)), vr, 'c',
                     range(len(ro0)), ro0, 'b', range(len(ro1)), ro1, 'm', range(len(aaa)), aaa, 'k')
        #self.ax.plot(range(len(vf)), vf, 'r')
        self.ax.legend(["fire", "man", "rej", "ro1", "ro2", "alarm"], loc="upper right")
        self.ax.grid(True)
        self.canvas.draw()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    root = MainWindow()
    root.show()
    sys.exit(app.exec_())

